/**
 * WebView提供器
 * 负责创建和管理VSCode WebView界面，提供远程文件浏览和配置管理功能
 * 
 * @author lihengtt <lihengsir@gmail.com>
 * @github https://github.com/lihengtt
 */

import * as vscode from 'vscode';
import { ConfigManager, RsyncConfig } from './configManager';
import { RemoteExplorer, RemoteFile } from './remoteExplorer';
import { FileWatcher } from './fileWatcher';
import { DeploymentManager } from './deploymentManager';
import { LogManager } from './logManager';

export class WebviewProvider implements vscode.WebviewViewProvider {
    public static readonly viewType = 'rsyncDeploymentView';
    
    private _view?: vscode.WebviewView;
    private configManager: ConfigManager;
    private remoteExplorer: RemoteExplorer;
    private deploymentManager: DeploymentManager;
    private fileWatcher: FileWatcher;
    private context: vscode.ExtensionContext;
    private logger: LogManager;
    
    // 状态缓存
    private cachedConfig: RsyncConfig | null = null;
    private cachedFiles?: RemoteFile[];
    private cachedCurrentPath?: string;
    private isConnected: boolean = false;

    /**
     * 构造函数
     * @param context - VSCode扩展上下文
     * @param configManager - 配置管理器实例
     * @param remoteExplorer - 远程文件浏览器实例
     * @param deploymentManager - 部署管理器实例
     * @param fileWatcher - 文件监控器实例
     * @author lihengtt <lihengsir@gmail.com>
     */
    constructor(
        context: vscode.ExtensionContext,
        configManager: ConfigManager,
        remoteExplorer: RemoteExplorer,
        deploymentManager: DeploymentManager, // 改为使用DeploymentManager
        fileWatcher: FileWatcher
    ) {
        this.context = context;
        this.configManager = configManager;
        this.remoteExplorer = remoteExplorer;
        this.deploymentManager = deploymentManager; // 改为使用DeploymentManager
        this.fileWatcher = fileWatcher;
        this.logger = LogManager.getInstance();
        
        // 初始化缓存
        this.loadCachedState();
    }

    /**
     * 解析WebView视图
     * @param webviewView - WebView视图
     * @param context - WebView视图解析上下文
     * @param token - 取消令牌
     * @author lihengtt <lihengsir@gmail.com>
     */
    public resolveWebviewView(
        webviewView: vscode.WebviewView,
        _context: vscode.WebviewViewResolveContext,
        _token: vscode.CancellationToken,
    ) {
        this._view = webviewView;

        webviewView.webview.options = {
            enableScripts: true,
            localResourceRoots: [
                this.context.extensionUri
            ]
        };

        webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);

        // 监听来自WebView的消息
        webviewView.webview.onDidReceiveMessage(
            message => {
                this.handleWebviewMessage(message);
            },
            undefined,
            this.context.subscriptions
        );

        // 监听WebView的显示/隐藏事件
        webviewView.onDidChangeVisibility(() => {
            if (webviewView.visible) {
                this.logger.info('WebView变为可见，恢复状态', 'WebviewProvider');
                // WebView变为可见时，恢复状态而不是重新加载
                this.restoreViewState();
            }
        });

        // 初始化界面
        this.refreshView();
    }

    /**
     * 处理来自WebView的消息
     * @param message - 消息对象
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async handleWebviewMessage(message: any) {
        this.logger.info(`收到webview消息: ${message.command}`, 'WebviewProvider');
        
        switch (message.command) {
            case 'refreshFiles':
                await this.refreshRemoteFiles(message.path);
                break;
            case 'downloadFile':
                await this.downloadFile(message.path);
                break;
            case 'uploadFile':
                await this.uploadFile(message.localPath, message.remotePath);
                break;
            case 'deleteFile':
                await this.deleteFile(message.path, message.isDirectory);
                break;
            case 'createDirectory':
                await this.createDirectory(message.path);
                break;
            case 'openConfig':
                await this.openConfigDialog();
                break;
            case 'toggleAutoSync':
                this.logger.info('开始处理toggleAutoSync命令', 'WebviewProvider');
                await this.toggleAutoSync();
                this.logger.info('toggleAutoSync命令处理完成', 'WebviewProvider');
                break;
            case 'syncAll':
                await this.syncAllFiles();
                break;
            case 'showOutput':
                this.remoteExplorer.showOutput();
                break;
            case 'testConnection':
                await this.testConnection();
                break;
            case 'navigateBack':
                await this.navigateBack();
                break;
            case 'navigateHome':
                await this.navigateHome();
                break;
            case 'navigateToPath':
                await this.navigateToPath(message.path);
                break;
            case 'runDiagnostics':
                await this.runDiagnostics();
                break;
            default:
                this.logger.warn(`未知的webview命令: ${message.command}`, 'WebviewProvider');
        }
    }

    /**
     * 刷新远程文件列表
     * @param remotePath - 远程路径
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async refreshRemoteFiles(remotePath?: string) {
        try {
            this.logger.debug(`刷新远程文件列表: ${remotePath || '默认路径'}`, 'WebviewProvider');
            const result = await this.remoteExplorer.listRemoteFiles(remotePath);
            
            if (result.success && result.files) {
                // 缓存文件列表和当前路径
                this.cachedFiles = result.files;
                this.cachedCurrentPath = this.remoteExplorer.getCurrentRemotePath();
                this.isConnected = true;
                this.saveCachedState();
                
                this.logger.info(`成功获取远程文件列表，共${result.files.length}个文件`, 'WebviewProvider');
            } else {
                this.isConnected = false;
                this.logger.warn(`获取远程文件列表失败: ${result.error}`, 'WebviewProvider');
            }
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'updateFiles',
                    files: result.files || [],
                    currentPath: this.remoteExplorer.getCurrentRemotePath(),
                    success: result.success,
                    error: result.error
                });
            }
        } catch (error) {
            // 处理连接错误，给用户友好的提示
            const errorMessage = `${error}`;
            this.isConnected = false;
            this.logger.error('刷新远程文件列表时发生错误', 'WebviewProvider', error);
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'updateFiles',
                    files: [],
                    currentPath: this.remoteExplorer.getCurrentRemotePath(),
                    success: false,
                    error: errorMessage
                });
            }
            
            // 如果是连接相关错误，提示用户测试连接
            if (errorMessage.includes('SSH连接') || errorMessage.includes('连接失败')) {
                vscode.window.showWarningMessage(
                    '无法连接到远程服务器，请点击"测试连接"按钮检查配置。',
                    '测试连接'
                ).then(selection => {
                    if (selection === '测试连接') {
                        this.testConnection();
                    }
                });
            }
        }
    }

    /**
     * 下载文件
     * @param remotePath - 远程文件路径
     */
    private async downloadFile(remotePath: string) {
        const success = await this.remoteExplorer.downloadFile(remotePath);
        
        if (this._view) {
            this._view.webview.postMessage({
                command: 'downloadResult',
                success,
                path: remotePath
            });
        }
    }

    /**
     * 上传文件 - 支持自动执行
     * @param localPath - 本地文件路径
     * @param remotePath - 远程文件路径
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async uploadFile(localPath: string, remotePath: string) {
        try {
            // 如果没有提供remotePath，使用当前远程路径
            let targetRemotePath = remotePath;
            if (!targetRemotePath) {
                // const config = this.configManager.getConfig();
                const currentPath = this.remoteExplorer.getCurrentRemotePath();
                const fileName = localPath.split(/[\\/]/).pop() || '';
                // 修复路径拼接逻辑，避免重复拼接
                targetRemotePath = currentPath.endsWith('/') ? 
                    `${currentPath}${fileName}`.replace(/\/+/g, '/') : 
                    `${currentPath}/${fileName}`.replace(/\/+/g, '/');
            }
            
            // 直接执行上传，不显示确认对话框
            const success = await this.deploymentManager.uploadFile(localPath, targetRemotePath);
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'uploadResult',
                    success: success,
                    localPath,
                    remotePath: targetRemotePath,
                    error: success ? null : '上传失败'
                });
            }

            // 刷新文件列表
            if (success) {
                await this.refreshRemoteFiles();
            }
        } catch (error) {
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'uploadResult',
                    success: false,
                    localPath,
                    remotePath: remotePath || '',
                    error: `上传失败: ${error}`
                });
            }
        }
    }

    /**
     * 删除文件
     * @param remotePath - 远程文件路径
     * @param isDirectory - 是否为目录
     */
    private async deleteFile(remotePath: string, isDirectory: boolean) {
        const success = await this.remoteExplorer.deleteRemoteFile(remotePath, isDirectory);
        
        if (this._view) {
            this._view.webview.postMessage({
                command: 'deleteResult',
                success,
                path: remotePath
            });
        }

        // 刷新文件列表
        if (success) {
            await this.refreshRemoteFiles();
        }
    }

    /**
     * 创建目录
     * @param remotePath - 远程目录路径
     */
    private async createDirectory(remotePath: string) {
        const success = await this.remoteExplorer.createRemoteDirectory(remotePath);
        
        if (this._view) {
            this._view.webview.postMessage({
                command: 'createDirectoryResult',
                success,
                path: remotePath
            });
        }

        // 刷新文件列表
        if (success) {
            await this.refreshRemoteFiles();
        }
    }

    /**
     * 打开配置对话框
     */
    private async openConfigDialog() {
        this.logger.info('打开配置对话框', 'WebviewProvider');
        await this.configManager.showConfigDialog();
        this.refreshView();
    }

    /**
     * 切换自动同步状态
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async toggleAutoSync() {
        try {
            this.logger.info('切换自动同步状态', 'WebviewProvider');
            
            // 修复方法调用，保持与extension.ts中命令注册的一致性
            await this.fileWatcher.toggle();
            
            // 获取当前状态并更新界面
            const isWatching = this.fileWatcher.isWatching();
            this.logger.info(`自动同步状态已切换为: ${isWatching ? '启用' : '禁用'}`, 'WebviewProvider');
            
            // 刷新视图以更新自动同步按钮状态
            this.refreshView();
            
            // 发送状态更新消息到webview
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'updateAutoSyncStatus',
                    isWatching: isWatching
                });
            }
            
            // 显示用户反馈消息
            const message = isWatching ? '自动同步已启用' : '自动同步已禁用';
            vscode.window.showInformationMessage(message);
            
        } catch (error) {
            const errorMessage = `切换自动同步状态失败: ${error}`;
            this.logger.error(errorMessage, 'WebviewProvider');
            vscode.window.showErrorMessage(errorMessage);
            
            // 发送错误消息到webview
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'toggleAutoSyncError',
                    error: errorMessage
                });
            }
        }
    }

    /**
     * 同步所有文件 - 支持自动执行
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async syncAllFiles() {
        try {
            // 直接执行同步，不显示确认对话框
            const success = await this.deploymentManager.syncAll();
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'syncAllResult',
                    success: success,
                    error: success ? null : '同步失败'
                });
            }
        } catch (error) {
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'syncAllResult',
                    success: false,
                    error: `同步失败: ${error}`
                });
            }
        }
    }

    /**
     * 返回上级目录
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async navigateBack() {
        const currentPath = this.remoteExplorer.getCurrentRemotePath();
        const parentPath = currentPath === '/' ? '/' : currentPath.substring(0, currentPath.lastIndexOf('/')) || '/';
        
        if (parentPath !== currentPath) {
            await this.refreshRemoteFiles(parentPath);
        }
    }

    /**
     * 返回根目录
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async navigateHome() {
        const config = this.configManager.getConfig();
        const homePath = config?.remotePath || '/';
        await this.refreshRemoteFiles(homePath);
    }

    /**
     * 跳转到指定路径
     * @param path - 目标路径
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async navigateToPath(path: string) {
        await this.refreshRemoteFiles(path);
    }

    /**
     * 测试SSH连接
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async testConnection() {
        try {
            const success = await this.deploymentManager.testConnection();
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'testConnectionResult',
                    success: success,
                    error: success ? null : '连接失败',
                    output: success ? '连接成功' : '连接失败'
                });
            }

            // 显示结果通知
            if (success) {
                vscode.window.showInformationMessage('SSH连接测试成功！服务器响应正常。');
            } else {
                vscode.window.showErrorMessage('SSH连接测试失败');
            }
        } catch (error) {
            const errorMessage = `测试SSH连接时发生错误: ${error}`;
            vscode.window.showErrorMessage(errorMessage);
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'testConnectionResult',
                    success: false,
                    error: errorMessage,
                    output: ''
                });
            }
        }
    }

    /**
     * 加载缓存状态
     * @author lihengtt <lihengsir@gmail.com>
     */
    private loadCachedState(): void {
        try {
            const cachedState = this.context.globalState.get<{
                config: RsyncConfig | null;
                files: RemoteFile[];
                currentPath: string;
                isConnected: boolean;
            }>('rsyncDeploymentState');
            
            if (cachedState) {
                this.cachedConfig = cachedState.config;
                this.cachedFiles = cachedState.files;
                this.cachedCurrentPath = cachedState.currentPath;
                // 连接状态不从缓存恢复，需要重新验证
                this.isConnected = false;
                
                this.logger.info(`成功加载缓存状态: 配置=${!!this.cachedConfig}, 文件=${this.cachedFiles?.length || 0}个, 路径=${this.cachedCurrentPath}`, 'WebviewProvider');
                
                // 如果有缓存的配置，更新远程浏览器的当前路径
                if (this.cachedCurrentPath) {
                    this.remoteExplorer.setCurrentRemotePath(this.cachedCurrentPath);
                }
            } else {
                this.logger.info('没有找到缓存状态，使用默认值', 'WebviewProvider');
            }
        } catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            this.logger.warn(`加载缓存状态失败: ${errorMessage}`, 'WebviewProvider');
        }
    }

    /**
     * 保存缓存状态
     * @author lihengtt <lihengsir@gmail.com>
     */
    private saveCachedState(): void {
        try {
            const stateToCache = {
                config: this.cachedConfig,
                files: this.cachedFiles || [],
                currentPath: this.cachedCurrentPath || '/',
                isConnected: this.isConnected
            };
            
            this.context.globalState.update('rsyncDeploymentState', stateToCache);
            this.logger.debug('缓存状态已保存', 'WebviewProvider');
        } catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            this.logger.warn(`保存缓存状态失败: ${errorMessage}`, 'WebviewProvider');
        }
    }

    /**
     * 恢复WebView状态
     * @author lihengtt <lihengsir@gmail.com>
     */
    private restoreViewState(): void {
        if (!this._view) {
            return;
        }

        const config = this.configManager.getConfig();
        const isWatching = this.fileWatcher.isWatching();
        
        // 发送配置信息
        this._view.webview.postMessage({
            command: 'updateConfig',
            config,
            isWatching,
            hasConfig: !!config
        });

        // 优先使用缓存的文件列表和路径
        if (this.cachedFiles && this.cachedCurrentPath && this.isConnected) {
            this.logger.info('恢复缓存的文件列表和路径', 'WebviewProvider');
            this._view.webview.postMessage({
                command: 'updateFiles',
                files: this.cachedFiles,
                currentPath: this.cachedCurrentPath,
                success: true,
                error: null
            });
        } else if (config && !this.cachedFiles) {
            // 如果没有缓存但有配置，则刷新文件列表
            const initialPath = config.remotePath || '/';
            this.logger.info(`没有缓存，刷新远程文件列表: ${initialPath}`, 'WebviewProvider');
            this.refreshRemoteFiles(initialPath);
        }
    }

    /**
     * 刷新视图
     * @author lihengtt <lihengsir@gmail.com>
     */
    public refreshView() {
        if (this._view) {
            const config = this.configManager.getConfig();
            const isWatching = this.fileWatcher.isWatching();
            
            // 更新缓存的配置
            this.cachedConfig = config;
            this.saveCachedState();
            
            // 发送配置更新消息
            this._view.webview.postMessage({
                command: 'updateConfig',
                config,
                isWatching,
                hasConfig: !!config
            });
            
            // 单独发送自动同步状态更新消息，确保按钮状态正确同步
            this._view.webview.postMessage({
                command: 'updateAutoSyncStatus',
                isWatching: isWatching
            });

            // 优先使用缓存的文件列表和路径
            if (this.cachedFiles && this.cachedCurrentPath && this.isConnected) {
                this.logger.info('使用缓存的文件列表和路径', 'WebviewProvider');
                this._view.webview.postMessage({
                    command: 'updateFiles',
                    files: this.cachedFiles,
                    currentPath: this.cachedCurrentPath,
                    success: true,
                    error: null
                });
            } else if (config) {
                // 如果没有缓存，则自动刷新文件列表
                const initialPath = config.remotePath || '/';
                this.logger.info(`首次加载，刷新远程文件列表: ${initialPath}`, 'WebviewProvider');
                this.refreshRemoteFiles(initialPath);
            }
        }
    }

    /**
     * 获取WebView的HTML内容
     * @param webview - WebView实例
     * @returns HTML字符串
     */
    private _getHtmlForWebview(webview: vscode.Webview) {
        // 获取资源URI
        const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this.context.extensionUri, 'resources', 'webview.js'));
        const styleUri = webview.asWebviewUri(vscode.Uri.joinPath(this.context.extensionUri, 'resources', 'webview.css'));

        // 生成nonce用于内容安全策略
        const nonce = this.getNonce();

        return `<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}'; sandbox allow-scripts allow-same-origin allow-modals;">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="${styleUri}" rel="stylesheet">
    <title>Rsync 部署</title>
</head>
<body>
    <div class="container">
        <!-- 配置区域 -->
        <div class="config-section">
            <div class="section-header">
                <h3>服务器配置</h3>
                <div class="config-buttons">
                    <button id="configBtn" class="btn btn-primary">配置</button>
                    <button id="testConnectionBtn" class="btn btn-secondary">测试连接</button>
                </div>
            </div>
            <div id="configStatus" class="config-status">
                <span class="status-text">未配置</span>
            </div>
        </div>

        <!-- 控制区域 -->
        <div class="control-section">
            <div class="control-buttons">
                <button id="refreshBtn" class="btn btn-secondary">刷新</button>
                <button id="syncAllBtn" class="btn btn-success">同步所有</button>
                <button id="autoSyncBtn" class="btn btn-toggle">自动同步</button>
                <button id="outputBtn" class="btn btn-info">查看日志</button>
                <button id="diagnosticsBtn" class="btn btn-warning">系统诊断</button>
            </div>
        </div>

        <!-- 路径导航 -->
        <div class="path-section">
            <div class="path-nav">
                <div class="path-controls">
                    <button id="backBtn" class="btn btn-nav" title="返回上级目录">↑</button>
                    <button id="homeBtn" class="btn btn-nav" title="返回根目录">🏠</button>
                </div>
                <div class="breadcrumb">
                    <span class="path-label">路径:</span>
                    <div id="breadcrumbPath" class="breadcrumb-path">/</div>
                </div>
            </div>
        </div>

        <!-- 文件列表 -->
        <div class="files-section">
            <div class="section-header">
                <h3>远程文件</h3>
                <button id="createDirBtn" class="btn btn-secondary">新建目录</button>
            </div>
            <div id="filesList" class="files-list">
                <div class="loading">加载中...</div>
            </div>
        </div>

        <!-- 状态栏 -->
        <div class="status-section">
            <div id="statusBar" class="status-bar">
                <span class="status-text">就绪</span>
            </div>
        </div>
    </div>

    <script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
    }

    /**
     * 生成随机nonce
     * @returns 随机字符串
     */
    private getNonce() {
        let text = '';
        const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        for (let i = 0; i < 32; i++) {
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }
        return text;
    }

    /**
     * 显示WebView
     */
    public show() {
        if (this._view) {
            this._view.show?.(true);
        }
    }

    /**
     * 获取WebView视图
     * @returns WebView视图或undefined
     */
    public getView(): vscode.WebviewView | undefined {
        return this._view;
    }

    /**
     * 运行系统诊断
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async runDiagnostics(): Promise<void> {
        try {
            this.logger.info('开始运行系统诊断', 'WebviewProvider');
            
            // 发送状态更新到webview
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'updateStatus',
                    message: '正在运行系统诊断...'
                });
            }

            // 调用extension.ts中的诊断命令
            await vscode.commands.executeCommand('rsyncDeployment.runDiagnostics');
            
            // 发送完成状态到webview
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'updateStatus',
                    message: '系统诊断完成，请查看诊断报告'
                });
            }
            
            this.logger.info('系统诊断完成', 'WebviewProvider');
        } catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            this.logger.error(`系统诊断失败: ${errorMessage}`, 'WebviewProvider');
            
            if (this._view) {
                this._view.webview.postMessage({
                    command: 'updateStatus',
                    message: `系统诊断失败: ${errorMessage}`
                });
            }
        }
    }
}